#ifndef XRPL_PEERFINDER_TUNING_H_INCLUDED
#define XRPL_PEERFINDER_TUNING_H_INCLUDED

#include <array>

namespace ripple {
namespace PeerFinder {

/** Heuristically tuned constants. */
/** @{ */
namespace Tuning {

enum {
    //---------------------------------------------------------
    //
    // Automatic Connection Policy
    //
    //---------------------------------------------------------

    /** Time to wait between making batches of connection attempts */
    secondsPerConnect = 10

    /** Maximum number of simultaneous connection attempts. */
    ,
    maxConnectAttempts = 20

    /** The percentage of total peer slots that are outbound.
        The number of outbound peers will be the larger of the
        minOutCount and outPercent * Config::maxPeers specially
        rounded.
    */
    ,
    outPercent = 15

    /** A hard minimum on the number of outgoing connections.
        This is enforced outside the Logic, so that the unit test
        can use any settings it wants.
    */
    ,
    minOutCount = 10

    /** The default value of Config::maxPeers. */
    ,
    defaultMaxPeers = 21

    /** Max redirects we will accept from one connection.
        Redirects are limited for security purposes, to prevent
        the address caches from getting flooded.
    */
    ,
    maxRedirects = 30
};

//------------------------------------------------------------------------------
//
// Fixed
//
//------------------------------------------------------------------------------

static std::array<int, 10> const connectionBackoff{
    {1, 1, 2, 3, 5, 8, 13, 21, 34, 55}};

//------------------------------------------------------------------------------
//
// Bootcache
//
//------------------------------------------------------------------------------

enum {
    // Threshold of cache entries above which we trim.
    bootcacheSize = 1000

    // The percentage of addresses we prune when we trim the cache.
    ,
    bootcachePrunePercent = 10
};

// The cool down wait between database updates
// Ideally this should be larger than the time it takes a full
// peer to send us a set of addresses and then disconnect.
//
static std::chrono::seconds const bootcacheCooldownTime(60);

//------------------------------------------------------------------------------
//
// Livecache
//
//------------------------------------------------------------------------------

// Drop incoming messages with hops greater than this number
std::uint32_t constexpr maxHops = 6;

// How many Endpoint to send in each mtENDPOINTS
std::uint32_t constexpr numberOfEndpoints = 2 * maxHops;

// The most Endpoint we will accept in mtENDPOINTS
std::uint32_t constexpr numberOfEndpointsMax =
    std::max<decltype(numberOfEndpoints)>(numberOfEndpoints * 2, 64);

// Number of addresses we provide when redirecting.
std::uint32_t constexpr redirectEndpointCount = 10;

// How often we send or accept mtENDPOINTS messages per peer
// (we use a prime number of purpose)
std::chrono::seconds constexpr secondsPerMessage(151);

// How long an Endpoint will stay in the cache
// This should be a small multiple of the broadcast frequency
std::chrono::seconds constexpr liveCacheSecondsToLive(30);

// How much time to wait before trying an outgoing address again.
// Note that we ignore the port for purposes of comparison.
std::chrono::seconds constexpr recentAttemptDuration(60);

}  // namespace Tuning
/** @} */

}  // namespace PeerFinder
}  // namespace ripple

#endif
